package com.huike.web.controller.common;

import javax.servlet.http.HttpServletResponse;

import com.alibaba.excel.EasyExcel;
import com.huike.clues.domain.vo.TbClueExcelVo;
import com.huike.clues.service.ITbClueService;
import com.huike.common.config.MinioConfig;
import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import com.huike.clues.service.ISysFileService;
import com.huike.common.core.controller.BaseController;
import com.huike.common.core.domain.AjaxResult;

import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * 通用请求处理
 */
@RestController
public class CommonController extends BaseController {
    private static final Logger log = LoggerFactory.getLogger(CommonController.class);

    @Autowired
    private ISysFileService fileService;

    //minio配置文件属性类
    @Autowired
    private MinioConfig minioConfig;

    @Autowired
    private ITbClueService iTbClueService;

    /**
     * 通用上传请求,合同PDF上传
     */
    @PostMapping("/common/upload")
    public AjaxResult uploadFile(MultipartFile file) {
        InputStream inputStream = null;
        //创建Minio的连接对象
        MinioClient minioClient = getClient();
        //桶对象
        String bucketName = minioConfig.getBucketName();
        try {
            inputStream = file.getInputStream();
            //基于官网的内容，判断文件存储的桶是否存在 如果桶不存在就创建桶
            boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (exists) {
                System.out.println("该桶已经存在");
            } else {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket("huike-crm").build());
            }
            /**
             * ================================操作文件================================
             * 思路：我们上传的文件是:文件.pdf
             * 那么我们应该上传到配置的bucket内 我们配置的bucketName是huike-crm
             * 那么我们存在桶里的文件应该是什么样的 也叫“文件.pdf”吗?
             * 应该按照上传的年月日进行区分
             * 举例：2021-05-05日进行上传的
             * 那么存在桶里的路径应该是
             * huike-crm/2021/05/05/这个目录下
             * 而对于同一个文件，存在重名问题，所以我们应该利用UUID生成一个新的文件名，并拼接上 .pdf 作为文件后缀
             * 那么完整的路径就是 huike-crm/2021/05/05/uuid.pdf
             *
             * 如果上述思路你无法理解，那么就直接存放在桶内生成uuid+.pdf即可
             * 即：huike-crm/uuid.pdf
             */
            //操作文件
            String fileName = file.getOriginalFilename();
            String objectName = new SimpleDateFormat("yyyy/MM/dd/").format(new Date()) + UUID.randomUUID().toString().replaceAll("-", "")
                    + fileName.substring(fileName.lastIndexOf("."));
            PutObjectArgs objectArgs = PutObjectArgs.builder().object(objectName)
                    .bucket(bucketName)
                    .contentType(file.getContentType())
                    .stream(file.getInputStream(), file.getSize(), -1).build();
            minioClient.putObject(objectArgs);
            //封装访问的url给前端
            AjaxResult ajax = AjaxResult.success();
            ajax.put("fileName", "/" + bucketName + "/" + objectName);
            //url需要进行截取
            ajax.put("url", minioConfig.getEndpoint() + ":" + minioConfig.getPort() + "/" + minioConfig.getBucketName() + "/" + fileName);
            /**
             * 构建返回结果集
             */

            /**
             * 封装需要的数据进行返回
             */
            return ajax;
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("上传失败");
        } finally {
            //防止内存泄漏
            if (inputStream != null) {
                try {
                    inputStream.close(); // 关闭流
                } catch (IOException e) {
                    log.debug("inputStream close IOException:" + e.getMessage());
                }
            }
        }
    }

    /**
     * 获取Minio连接
     *
     * @return MinioClient minio连接对象
     */
    private MinioClient getClient() {
        MinioClient minioClient =
                MinioClient.builder()
                        .endpoint("http://" + minioConfig.getEndpoint() + ":" + minioConfig.getPort())
                        .credentials(minioConfig.getAccessKey(), minioConfig.getSecretKey())
                        .build();
        return minioClient;
    }

    /**
     * 下载模板的接口,无填充方式导出并下载xlsx
     *
     * @param response
     * @throws IOException
     */
    @GetMapping("common/download")
    public void download(HttpServletResponse response) throws IOException {
        //从数据库查询数据
//        List<TbClueExcelVo> list = iTbClueService.selectAll();
        //调用方法(默认下载文件名,响应的网页,数据实体类,数据)
        CommonController.downloadUnfilledToXlsx("clueTemplate", response, TbClueExcelVo.class, null);
    }

    /**
     * 导入工具类
     *
     * @param excelName 默认下载文件名
     * @param response  响应的网页
     * @param cla       数据实体类
     * @param list      数据
     * @throws IOException
     */
    public static void downloadUnfilledToXlsx(String excelName, HttpServletResponse response, Class cla, List list) throws IOException {
        // 这里注意 使用swagger 会导致各种问题，easyexcel官方文档推荐直接用浏览器或者用postman测试
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode(excelName, "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), cla).sheet(excelName).doWrite(list);
    }
}